/// 基于mixmin 继承机制,只有一个超类
/// Extension方法是一种不更改类或创建子类的时候添加功能
/// 成员访问使用 . 或者 ?.
main(List<String> args) {
  classTest();
}

void classTest() {
  // var p = Point(x: 1, y: 1);
  // print(p.runtimeType); // 输出  Point
  // var o = Point(x: 1);
  // print(o.y);
}

class Point {
  num x; // 默认是null
  num y;
  num z = 0;
  // 构造函数1：
  // Point(num x, num yy) {
  //   this.x = x; // 使用this的场景是函数参数和实例变量冲突的时候，不冲突的时候不用this.
  //   y = yy;
  // }

  // 构造函数2：(可选命名参数可以指定默认值)
  // Point({this.x, this.y = 5});

  // 构造函数3：
  Point(this.x, this.y);

  // 构造函数4：(可选位置参数可以指定默认值)
  // Point(this.x, [this.y = 5]);

  // 构造函数5：
  // Point([this.x = 6, this.y = 6]);

  // 构造函数6：
  Point.from({this.x = 1, this.y = 1});
  // 构造函数7：
  Point.to(num x, num y) {
    this.x = x;
    this.y = y;
  }
  // 构造函数8：
  Point.abs(x, {num y}) {}
  // 构造函数9：
  Point.cd(x, {this.y = 5}) {}
}

/// 构造函数不能继承，如果想在子类中使用父类同名的构造函数（非默认构造函数），需要在子类中显示的声明
/// 默认情况下,子类会调用父类的无参构造函数（注意，这个构造函数不会自动生成，需要手动实现），会在子类构造函数执行前执行。
/// 默认构造函数只能有一个，如果父类没有实现的话，子类会报错
/// 如果子类有初始化列表，那么初始化列表会在父类默认构造函数执行前执行。
/// 总结：子类的构造函数调用顺序 1.初始化列表 2. 父类默认构造函数 3.当前构造函数

class Person {
  String firstName;
  Person.fromJson(Map data) {
    print('in Person');
  }
  Person() {}
}

class Employee extends Person {
  num a;
  final num b = 1;
  Employee.a(Map data) : super.fromJson(data);
  // Employee(num a) {}
}

/// 重定向构造函数
class Rect {
  num x, y;
  Rect(this.x, this.y);
  Rect.alongX(num x) : this(x, 0);
  // Rect(num x) {} ，默认构造函数只有一个
}

/// 工厂构造函数
/// 工厂构造函数无法访问this
///
/// 抽象类（无法实例化）（常用于声明接口方法，如果想让抽象类可以实例化，可以给他定义工厂构造函数）

abstract class A {}

/// 隐式接口：每一个类都隐式的定义一个接口并实现了该接口，接口实现了该类的实例成员，及这个类的其他接口（A类支持调用B类的API，但是不想继承B类，可以使用接口的形式）

class B {}

class D {}

class C implements B, D {}

/// 类扩展：dart 2.7 新增的方法
/// 如果扩展的方法重名了可以使用 hide 和 rad。（具体的等应用吧）

extension NumParsing on String {
  int parseInt() {
    return int.parse(this);
  }
}

/// Mixin 可以让A类 使用B 类的方法
///
